package com.csx.base.concurrency.aqs.reentrantlock;

import com.csx.base.concurrency.util.TimeUtil;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * <p> what does this class do ? </p>
 *   该案例演示可以打断的获取锁
 * <p> How does it work ?</p>
 * <p> Why does it do this ?</p>
 *
 * @author cuisongxu
 * @date 2024/12/2 周一 9:44
 */
public class ReentrantLockInterruptLockTest {

    private final ReentrantLock lock = new ReentrantLock();

    // 入口方法
    public void test() {
        Thread thread1 = new Thread(new LongTimeTask(), "thread1");
        Thread thread2 = new Thread(new TwoSecondsTask(), "thread2");
        Thread thread3 = new Thread(new InterruptTask(thread2), "thread3");
        try {
            thread1.start();
            thread2.start();
            // 等待thread2启动完毕，尝试获取锁
            TimeUnit.SECONDS.sleep(1);
            // 启动thread3打断thread2获取锁
            thread3.start();
            // 等待三个线程执行完毕
            thread1.join();
            thread2.join();
            thread3.join();
            System.out.println("主线程执行完毕");

        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

    }

    class TwoSecondsTask implements Runnable {
        @Override
        public void run() {
            boolean isInterrupt = false;
            try {
                String nowTimeStr = TimeUtil.getNowTimeStr();
                System.out.println(nowTimeStr + " " + Thread.currentThread().getName() + " 尝试获取锁");
                lock.lockInterruptibly();
                try {
                    // 模拟处理延迟
                    TimeUnit.SECONDS.sleep(2);
                }catch (InterruptedException e) {
                    lock.unlock();
                    e.printStackTrace();
                }
            } catch (InterruptedException e) {
                isInterrupt = true;
                String nowTimeStr = TimeUtil.getNowTimeStr();
                System.out.println(nowTimeStr + " " + Thread.currentThread().getName() + " 获取锁被打断");
            }
            // 执行其它任务
            System.out.println("执行其它任务,是否被打断:" + isInterrupt);
        }
    }
    static class InterruptTask implements Runnable {

        private final Thread needToInterruptThead;

        public InterruptTask(Thread needToInterruptThead) {
            this.needToInterruptThead = needToInterruptThead;
        }
        @Override
        public void run() {
            String nowTimeStr = TimeUtil.getNowTimeStr();
            System.out.println(nowTimeStr + " " + Thread.currentThread().getName() + " 打断 " + needToInterruptThead.getName());
            needToInterruptThead.interrupt();
        }
    }



    class LongTimeTask implements Runnable {

        @Override
        public void run() {
            lock.lock();
            try {
                // 模拟长任务的执行时长,这会导致长时间持有锁,后续想要获取锁的线程只能进入阻塞队列等待释放锁
                TimeUnit.SECONDS.sleep(99999);
            }catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    }
}
